package com.virjar.ucrack.apphook;

import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import com.virjar.hermes.hermesagent.hermes_api.EmbedHermes;
import com.virjar.ucrack.plugin.LogUtil;
import com.virjar.ucrack.plugin.hotload.XposedHotLoadCallBack;
import com.virjar.xposed_extention.ClassLoadMonitor;
import com.virjar.xposed_extention.SharedObject;
import com.virjar.xposed_extention.SingletonXC_MethodHook;
import com.virjar.xposed_extention.XposedReflectUtil;

import org.apache.commons.lang3.StringUtils;

import java.util.Set;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class WeiShiHook implements XposedHotLoadCallBack {
    private static final String TAG = "weishi";

    @Override
    public void onXposedHotLoad() {
        EmbedHermes.bootstrap("com.virjar.ucrack.hermes.weishi", WeiShiHook.class);
        openLog();
        hook();
    }


    private void hook() {

        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.module.e.b.a.b", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                Log.i("weijia", "个人详情数据，查询堆栈:" + LogUtil.getTrack());
            }
        });

        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.utils.network.wns.f", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                XposedHelpers.findAndHookMethod(clazz, "a", XposedHelpers.findClass("com.tencent.oscar.utils.network.d", clazz.getClassLoader()), new SingletonXC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i("weijia", "send body:" + JSONObject.toJSON(param.args[0]));
                        Log.i("weijia", "bean class:" + param.args[0].getClass());
                    }
                });
            }
        });


    }


    private void backup() {
        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.base.service.TinListService", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {

                XposedReflectUtil.findAndHookOneMethod(clazz, "onReply", new SingletonXC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        LogUtil.outLog("search request: " + JSONObject.toJSONString(param.args[0]));
                        LogUtil.outLog("search response: " + JSONObject.toJSONString(XposedHelpers.callMethod(param.args[1], "d")));
                    }
                });

            }
        });

        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.module.discovery.ui.GlobalSearchActivity", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                XposedReflectUtil.monitorMethodCall(clazz, "a");
            }
        });

        ClassLoadMonitor.addClassLoadMonitor("com.tencent.wns.network.ConnectionImpl", new ClassLoadMonitor.OnClassLoader() {
            private Set<Class<?>> hookedClass = Sets.newConcurrentHashSet();

            @Override
            public void onClassLoad(Class clazz) {
                XposedBridge.hookAllConstructors(clazz, new SingletonXC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        if (hookedClass.contains(param.thisObject.getClass())) {
                            return;
                        }
                        synchronized (WeiShiHook.class) {

                            Log.i("weijia", "创建connection对象:" + LogUtil.getTrack());

                            if (hookedClass.contains(param.thisObject.getClass())) {
                                return;
                            }
                            hookedClass.add(param.thisObject.getClass());

                            XposedReflectUtil.findAndHookMethodWithSupperClass(param.thisObject.getClass(), "SendData", byte[].class, int.class, int.class, int.class, new SingletonXC_MethodHook() {
                                @Override
                                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                    Log.i("weijia", param.thisObject.getClass() + ":发送请求：data:  param1:" + param.args[1] + "  param2:" + param.args[2] + " param3:" + param.args[3]);
                                    LogUtil.outLog("发送请求：data:  param1:" + param.args[1] + "  param2:" + param.args[2] + " param3:" + param.args[3]);
                                    LogUtil.outLog((byte[]) param.args[0]);
                                    Log.i("weijia", param.thisObject + " 请求发送堆栈:" + LogUtil.getTrack());
                                }
                            });
                        }
                    }
                });

            }
        });

        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.module.discovery.ui.adapter.h", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                XposedBridge.hookAllConstructors(clazz, new SingletonXC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i("weijia", "create a request: " + JSONObject.toJSONString(param.args));
                        Log.i("weijia", "the stack trace: " + LogUtil.getTrack());
                    }
                });

                XposedReflectUtil.findAndHookOneMethod(clazz, "setListener", new SingletonXC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i("weijia", "attach request callback:" + param.args[0].getClass());
                        Log.i("weijia", "the stack trace:" + LogUtil.getTrack());
                    }
                });
            }
        });

        XposedHelpers.findAndHookMethod("com.tencent.oscar.base.service.TinListService", SharedObject.loadPackageParam.classLoader, "onReply",
                XposedHelpers.findClass("com.tencent.oscar.utils.network.d", SharedObject.loadPackageParam.classLoader),
                XposedHelpers.findClass("com.tencent.oscar.utils.network.e", SharedObject.loadPackageParam.classLoader),
                new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "TinListService a :" + JSONObject.toJSONString(param.args[0]) + "," + JSONObject.toJSONString(param.args[1]));
                    }
                });


        XposedBridge.hookAllMethods(XposedHelpers.findClass("com.tencent.wns.util.WupTool", SharedObject.loadPackageParam.classLoader), "encodeWup", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                Log.i(TAG, "encodeWup track:" + LogUtil.getTrack());
                Log.i(TAG, "data before encode:" + JSONObject.toJSONString(param.args[0]));
            }
        });

        XposedBridge.hookAllMethods(XposedHelpers.findClass("com.tencent.wns.util.WupTool", SharedObject.loadPackageParam.classLoader), "decodeWup", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                String paramStr = "";
                for (int i = 0; i < param.args.length; i++) {
                    paramStr += JSONObject.toJSONString(param.args[0]);
                }

                LogUtil.outLog("WupTool decodeWup :" + paramStr);
            }
        });


        XposedHelpers.findAndHookMethod("com.tencent.component.network.downloader.impl.a", SharedObject.loadPackageParam.classLoader, "a",
                XposedHelpers.findClass("org.apache.http.HttpResponse", SharedObject.loadPackageParam.classLoader),
                XposedHelpers.findClass("com.tencent.component.network.downloader.DownloadResult", SharedObject.loadPackageParam.classLoader),
                XposedHelpers.findClass("com.tencent.component.network.utils.thread.e.c", SharedObject.loadPackageParam.classLoader),
                int.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "com.tencent.component.network.module.a.b param:" + "," + param.args[1].toString());
                    }

                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "com.tencent.component.network.module.a.b result:" + JSONObject.toJSONString(param.getResult()));
                    }
                });


        XposedHelpers.findAndHookMethod("com.tencent.oscar.utils.al", SharedObject.loadPackageParam.classLoader, "a", String.class, String.class, String.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                Log.i(TAG, "com.tencent.oscar.utils.al:" + JSONObject.toJSONString(param.args[0]) + "," + JSONObject.toJSONString(param.args[1]) + "," + JSONObject.toJSONString(param.args[2]));
            }
        });

        XposedHelpers.findAndHookConstructor("com.tencent.ttpic.qzcamera.data.MusicMaterialMetaDataBean", SharedObject.loadPackageParam.classLoader, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                Log.i(TAG, "MusicMaterialMetaDataBean:" + JSONObject.toJSONString(param.args[0]));
            }

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                Log.i(TAG, "MusicMaterialMetaDataBean:" + JSONObject.toJSONString(param.getResult()));
            }
        });
    }

    private void openLog() {
        ClassLoadMonitor.addClassLoadMonitor("com.tencent.oscar.base.utils.Logger", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                XposedHelpers.findAndHookMethod(clazz, "i", String.class, String.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "log i :" + JSONObject.toJSONString(param.args[0]) + "," + JSONObject.toJSONString(param.args[1]));
                    }
                });

                XposedHelpers.findAndHookMethod(clazz, "e", String.class, String.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "log e :" + JSONObject.toJSONString(param.args[0]) + "," + JSONObject.toJSONString(param.args[1]));
                    }
                });

                XposedHelpers.findAndHookMethod(clazz, "v", String.class, String.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "log v :" + JSONObject.toJSONString(param.args[0]) + "," + JSONObject.toJSONString(param.args[1]));
                    }
                });


            }
        });

        ClassLoadMonitor.addClassLoadMonitor("tencent.tls.report.QLog", new ClassLoadMonitor.OnClassLoader() {
            @Override
            public void onClassLoad(Class clazz) {
                XposedHelpers.findAndHookMethod(clazz, "i", String.class, long.class, new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        Log.i(TAG, "Qlog :" + JSONObject.toJSONString(param.args[0]) + ",");
                    }
                });
            }
        });


    }


    @Override
    public boolean needHook(XC_LoadPackage.LoadPackageParam loadPackageParam) {
        return StringUtils.startsWithIgnoreCase(loadPackageParam.packageName, "com.tencent.weishi");
    }
}